﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace BaseSimpleAPI
{
    public class Token
    {
        // 相关ID
        public long Id { get; set; }

        // 颁发时间
        public DateTime IssueTime { get; set; }

        // 过期时间
        public DateTime ExpirationTime { get; set; }

        // 用户自定数据
        public string UserData { get; set; }

        // 场景名
        public string SceneName { get; set; }

        // 是否过期
        public bool IsExpiration { get { return DateTime.Now.Ticks > ExpirationTime.Ticks; } }
    }

    public class TokenHelper
    {
        private TokenHelper()
        {
            key_items = new[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", ".", "-", "_", "=", "+", "/" };
            random = new Random((int)DateTime.Now.Ticks);
            Password = GetRandomKey();
        }

        private static TokenHelper _TokenHelper = null;
        private static object _lock = new object();

        public static TokenHelper GetInstance()
        {
            if (_TokenHelper == null) lock (_lock) if (_TokenHelper == null)
                        _TokenHelper = new TokenHelper();

            return _TokenHelper;
        }

        /// <summary>
        /// 小票的有效时间（分钟）
        /// </summary>
        public long TokenEffectiveTime { get; set; } = 20;

        /// <summary>
        /// 将对应的实例转换为字符串
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public string ChangeToString(Token token)
        {
            string json = JsonConvert.SerializeObject(token);
            return Encryption(json);
        }

        /// <summary>
        /// 将字符串转换为小票
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public Token ChangeToToken(string token)
        {
            if (string.IsNullOrEmpty(token))
                return null;

            string json = Decrypt(token);
            return JsonConvert.DeserializeObject<Token>(json);
        }

        Random random = null;// new Random((int)DateTime.Now.Ticks);
        string[] key_items = null;

        /// <summary>
        /// 获取随机的Key
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public string GetRandomKey(int count = 8)
        {
            var items = new string[count];
            for (int i = 0; i < count; i++)
            {
                items[i] = key_items[random.Next((int)key_items.Length)];
            }

            return string.Join("", items);
        }

        /// <summary>
        /// 加密解密使用的密码
        /// </summary>
        private string Password { get; set; }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="express"></param>
        /// <returns></returns>
        public static string Encryption(string express)
        {
            //CspParameters param = new CspParameters();
            //param.KeyContainerName = GetInstance().Password;
            //using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(param))
            //{
            //    byte[] plaindata = Encoding.Default.GetBytes(express);//将要加密的字符串转换为字节数组
            //    byte[] encryptdata = rsa.Encrypt(plaindata, false);//将加密后的字节数据转换为新的加密字节数组
            //    return Convert.ToBase64String(encryptdata);//将加密后的字节数组转换为字符串
            //}

            // TODO bianchx:这个地方不好使需要处理一下
            return express;
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="ciphertext"></param>
        /// <returns></returns>
        public static string Decrypt(string ciphertext)
        {
            //CspParameters param = new CspParameters();
            //param.KeyContainerName = GetInstance().Password;
            //using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(param))
            //{
            //    byte[] encryptdata = Convert.FromBase64String(ciphertext);
            //    byte[] decryptdata = rsa.Decrypt(encryptdata, false);
            //    return Encoding.Default.GetString(decryptdata);
            //}

            // TODO bianchx:这个地方不好使需要处理一下
            return ciphertext;
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <returns></returns>
        public static string MD5Encrypt(string input)
        {
            return MD5Encrypt(input, new UTF8Encoding());
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="input">需要加密的字符串</param>
        /// <param name="encode">字符的编码</param>
        /// <returns></returns>
        public static string MD5Encrypt(string input, Encoding encode)
        {
            if (string.IsNullOrEmpty(input))
            {
                return null;
            }
            MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
            byte[] data = md5Hasher.ComputeHash(encode.GetBytes(input));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }
    }
}
